1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License.  You may obtain a copy
6    * of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  
17  package com.google.common.util.concurrent.testing;
18  
19  import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
20  
21  import com.google.common.annotations.Beta;
22  import com.google.common.util.concurrent.ListenableFuture;
23  
24  import junit.framework.Assert;
25  
26  import java.util.concurrent.CountDownLatch;
27  import java.util.concurrent.ExecutionException;
28  import java.util.concurrent.TimeUnit;
29  
30  /**
31   * A simple mock implementation of {@code Runnable} that can be used for
32   * testing ListenableFutures.
33   *
34   * @author Nishant Thakkar
35   * @since 10.0
36   */
37  @Beta
38  public class MockFutureListener implements Runnable {
39    private final CountDownLatch countDownLatch;
40    private final ListenableFuture<?> future;
41  
42    public MockFutureListener(ListenableFuture<?> future) {
43      this.countDownLatch = new CountDownLatch(1);
44      this.future = future;
45  
46      future.addListener(this, directExecutor());
47    }
48  
49    @Override
50    public void run() {
51      countDownLatch.countDown();
52    }
53  
54    /**
55     * Verify that the listener completes in a reasonable amount of time, and
56     * Asserts that the future returns the expected data.
57     * @throws Throwable if the listener isn't called or if it resulted in a
58     *     throwable or if the result doesn't match the expected value.
59     */
60    public void assertSuccess(Object expectedData) throws Throwable {
61      // Verify that the listener executed in a reasonable amount of time.
62      Assert.assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS));
63  
64      try {
65        Assert.assertEquals(expectedData, future.get());
66      } catch (ExecutionException e) {
67        throw e.getCause();
68      }
69    }
70  
71    /**
72     * Verify that the listener completes in a reasonable amount of time, and
73     * Asserts that the future throws an {@code ExecutableException} and that the
74     * cause of the {@code ExecutableException} is {@code expectedCause}.
75     */
76    public void assertException(Throwable expectedCause) throws Exception {
77      // Verify that the listener executed in a reasonable amount of time.
78      Assert.assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS));
79  
80      try {
81        future.get();
82        Assert.fail("This call was supposed to throw an ExecutionException");
83      } catch (ExecutionException expected) {
84        Assert.assertSame(expectedCause, expected.getCause());
85      }
86    }
87  
88    public void assertTimeout() throws Exception {
89      // Verify that the listener does not get called in a reasonable amount of
90      // time.
91      Assert.assertFalse(countDownLatch.await(1L, TimeUnit.SECONDS));
92    }
93  }